<template>
    <div class="api forbid-select" @click="close" ref="el">
        <div class="api-doc" @click.prevent.stop>
            <el-scrollbar style="width: 100%;height: 100%;border-radius: 5px;">
                <div class="toolbar">
                    <el-button style="font-size: 20px;font-family: inherit;" circle @click="showHelp">?</el-button>
                    <el-button style="font-size: 18px" :icon="getIcon('Close')" circle @click="close" />
                    <el-button style="font-size: 18px" :icon="getIcon('Position')" :disabled="loading" circle
                        @click="runInterface" />
                </div>
                <el-collapse v-model="activeNames" class="collapse">
                    <el-collapse-item class="title-header" name="1" disabled>
                        <template #title>
                            <span style="width: calc(100% - 125px);text-align: left;" class="no-wrap">
                                {{ props.interfaceInfo.comments ? ('【' + props.interfaceInfo.comments + '】接口调试') :
                                    '接口调试' }}
                            </span>
                        </template>
                        <el-row style="height: fit-content">
                            <div class="api-header">
                                <div class="address">
                                    <div class="title">接口地址：</div>
                                    <el-tag style="min-width: 100px" @dblclick="copy">
                                        {{ "https://api.dansj.cn" + props.interfaceInfo.url }}
                                    </el-tag>
                                </div>
                                <div class="method">
                                    <div class="title">接口方法：</div>
                                    <el-tag style="min-width: 50px">{{ upper(props.interfaceInfo.method) }}
                                    </el-tag>
                                </div>
                            </div>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="请求参数" name="2" class="title-h2 params">
                        <el-table :data="props.interfaceInfo.params" stripe border
                            header-cell-class-name="el-table-header-cell" cell-class-name="el-table-cell"
                            class="e-page request-table">
                            <el-table-column prop="name" label="参数名称" min-width="20%" />
                            <el-table-column prop="content" label="参数说明" min-width="30%" />
                            <el-table-column prop="required" label="是否必填" min-width="20%">
                                <template #default="scope">
                                    {{ scope.row.required === 1 || scope.row.required === '1' ? '是' : '否' }}
                                </template>
                            </el-table-column>
                            <el-table-column prop="value" label="参数值" min-width="20%" class-name="params-value">
                                <template #default="scope">
                                    <el-input size="small" v-model="scope.row.value"></el-input>
                                    <div :class="`errorItem animate__animated ${error ? 'animate__tada' : ''}`"
                                        v-show="scope.row.required in [1, '1'] && (scope.row.value === '' || scope.row.value === null)">
                                        必填项不能为空
                                    </div>
                                </template>
                            </el-table-column>
                        </el-table>
                    </el-collapse-item>
                    <el-collapse-item title="响应参数" name="3" class="title-h2 response">
                        <el-row>
                            <el-table :data="returnParams" stripe border header-cell-class-name="el-table-header-cell"
                                cell-class-name="el-table-cell" class="e-page request-table">
                                <el-table-column prop="name" label="参数名称" min-width="30%" />
                                <el-table-column prop="type" label="参数类型" min-width="20%">
                                    <template #default="scope">
                                        <span>{{
                                            scope.row.name === 'data' ? props.interfaceInfo.return_type === 'unknown' ?
                                                '具体以返回的数据类型为准' :
                                                props.interfaceInfo.return_type : scope.row.type
                                        }}</span>
                                    </template>
                                </el-table-column>
                                <el-table-column prop="content" label="参数说明" min-width="30%">
                                    <template #default="scope">
                                        {{ scope.row.content }}
                                    </template>
                                </el-table-column>
                                <el-table-column prop="default" label="默认值" min-width="20%" />
                            </el-table>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="数据说明" name="5" class="title-h2 response"
                        v-if="props.interfaceInfo.response && JSON.parse(props.interfaceInfo.response).length > 0">
                        <el-row>
                            <el-table :data="JSON.parse(props.interfaceInfo.response)" stripe border
                                header-cell-class-name="el-table-header-cell" cell-class-name="el-table-cell"
                                class="e-page">
                                <el-table-column prop="name" label="参数名称" min-width="35%" />
                                <el-table-column prop="type" label="参数类型" min-width="20%" />
                                <el-table-column prop="comment" label="参数说明" min-width="45%" />
                            </el-table>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="返回数据" name="4" disabled style="position:relative;"
                        class="return-data title-h2">
                        <div class="cost" v-if="cost >= 0">请求耗时{{ cost }}ms</div>
                        <highlightjs language="json" :code="returnData" v-show="returnData" />
                    </el-collapse-item>
                </el-collapse>
            </el-scrollbar>
        </div>
    </div>
</template>

<script setup>
import { apiPrefix } from "@/utils/constant"
import { formatJson, getIcon } from "@/utils/tools"
import { useElMessage, useElMessageBox, useRequest, useImagePreview, useCopyText } from "@usehook"
import image from "@/assets/image/wxmp-danjs.png"

const emits = defineEmits(["close"])

let activeNames = $ref(['1', '2', '4'])
let returnParams = [
    { name: "curPage", content: "当前页数, 0表示未开启分页功能", default: "0", type: "int", value: "" },
    { name: "curRecords", content: "当前页记录数", default: "1", type: "int", value: "" },
    { name: "data", content: "返回的数据", default: "", type: "", value: "" },
    { name: "message", content: "描述", default: "查询成功", type: "string", value: "" },
    { name: "pageLimit", content: "每页显示条数", default: "10", type: "int", value: "" },
    { name: "status", content: "响应状态", default: "true", type: "boolean", value: "" },
    { name: "totalPage", content: "总页数", default: "-1", type: "int", value: "" },
    { name: "totalRecords", content: "总条数", default: "1", type: "int", value: "" },
    { name: "responseStartTime", content: "请求开始时间", default: "sysdate", type: "string", value: "" },
    { name: "responseEndTime", content: "请求结束时间", default: "sysdate", type: "string", value: "" },
    { name: "version", content: "版本号", default: "-1", type: "string", value: "" }
]
let returnData = $ref("")
let cost = $ref(-1)
let error = $ref(false)
let loading = $ref(false)
let timeout = $ref(null)

const showHelp = () => {
    useElMessageBox("使用说明", h('p', null, [
        h('div', null, '系统中接口调用和调试均使用系统内部的token，部分接口不支持在线调试。'),
        h('div', null, '如果您需要在您的项目中使用该接口，需要申请token，然后在请求中携带token参数即可。'),
        h('br'),
        h('div', null, 'token参数使用方法：'),
        h('div', { style: "word-break: break-all;" }, ["1.请求参数中携带token，如", h('span', { style: 'padding:0 5px;color:red' }, 'https://api.dansj.cn/xxx?token=申请的token')]),
        h('div', null, ["2.在header中添加token参数", h('span', { style: 'padding:0 5px;color:red' }, '{"token":"申请的token"}')]),
        h('br'),
        h("div", null, "每个token根据等级不同每天可访问的次数上限有所区别，具体在小程序中查看对应的次数及QPS"),
        h('br'),
        h('div', null, ["token申请请关注",
            h('span', { onclick: () => { useImagePreview({ url: image, zIndex: 5000 }) }, class: "cursor-pointer", style: "color:red;cursor:pointer;padding:0 5px;font-size:20px" }, "微信小程序"),
            h('span', null, "或者微信公众号:"),
            h('span', { style: "color:red;padding:0 5px;font-size:20px" }, "dansj")])
    ]), { showIcon: false, customClass: "interface-help", showClose: true, showConfirmButton: false, closeOnClickModal: true })
}

const copy = (e) => {
    useCopyText(e.target.innerText).then(() => {
        useElMessage.success("接口地址复制成功")
    })
}

const errorCaution = () => {
    clearTimeout(timeout)
    error = true
    timeout = setTimeout(() => {
        error = false
    }, 1000)
}
const close = () => {
    emits("close")
}
const runInterface = () => {
    loading = true
    setTimeout(() => {
        loading = false
    }, 1000)


    let params = {}
    for (let p of props.interfaceInfo.params) {
        if (p.required === 1 && (p.value === '' || p.value === null || p.value === undefined)) {
            if (!("2" in activeNames)) {
                activeNames.push("2")
                setTimeout(() => {
                    errorCaution()
                }, 150)
            } else {
                errorCaution()
            }
            return
        }
        params[p.name] = p.value
    }

    const lastRunTime = sessionStorage.getItem("lastRunTime")
    if (lastRunTime && new Date().getTime() - parseInt(lastRunTime) < 10000) {
        useElMessage.error("请求过于频繁, " + Math.ceil((10 - (new Date().getTime() - parseInt(lastRunTime)) / 1000)) + "s后在尝试")
        return
    } else {
        sessionStorage.setItem("lastRunTime", new Date().getTime().toString())
    }

    useRequest({
        url: apiPrefix + props.interfaceInfo.url,
        ...params,
        method: props.interfaceInfo.method
    }).then(result => {
        let { sourcecode, ..._returnData } = result
        cost = new Date(_returnData.responseEndTime).getTime() - new Date(_returnData.responseStartTime).getTime()
        returnData = formatJson(_returnData)
    }).catch(err => {
        returnData = formatJson(err)
    })
}
const upper = (val) => {
    if (val) {
        return val.toUpperCase()
    }
    return ""
}

const el = $ref(null)
onMounted(() => {
    document.body.append(el)
})

const props = defineProps({
    interfaceInfo: {
        type: Object,
        required: true
    }
})

// watch(props.interfaceInfo, (info) => {
//     for (let param of info.params) {
//         if (param.name === 'token' && !param.value) param.value = getUserInfo.value.apiToken
//     }
// }, { deep: true, immediate: true })

</script>

<style lang="scss" scoped>
:deep(.api-doc) {
    position: absolute;
    top: 51px;
    left: 10px;
    height: calc(100vh - 110px);
    width: calc(100vw - 20px);
    z-index: 999;
    background: var(--background);
    border-radius: 5px;
}

.mobile .api-doc {
    height: calc(100% - 65px);
    top: 5px;
}

:deep(.request-table) {
    width: 100%;
    font-size: var(--font-size);
}

.mobile .request-table {
    width: 97%;
}

:deep(.address) {
    display: flex;
    align-items: center;
    justify-content: center;
}

:deep(.method) {
    display: flex;
    align-items: center;
    justify-content: center;
}

:deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
}

:deep(.toolbar) {
    position: absolute;
    right: 8px;
    top: 8px;
    z-index: 999;
    border-radius: 15px;
}

:deep(.result) {
    margin-left: 5px;
}

:deep(.title) {
    min-width: 100px;
    font-size: var(--font-size);
    justify-content: center;
    align-items: center;
    display: flex;
}

.mobile .title {
    display: none
}

:deep(.el-tag) {
    font-size: var(--font-size);
    padding: 10px;
    height: fit-content;
}

:deep(.el-collapse-item__arrow) {
    margin: 1px 0 0 10px;
}

:deep(.el-collapse-item__content) {
    padding-bottom: 5px;
}

:deep(.el-collapse-item__content:last-child) {
    padding-bottom: 0;
}

:deep(.el-collapse-item__header) {
    height: 45px;
    font-size: 13px;
    border-bottom: none;
    padding-left: 10px;
}

:deep(.e-page) {
    margin-top: 0;
    margin-bottom: -1px;
}

:deep(div[role="tab"]) {
    border-bottom: 1px solid var(--border-color);
}

:deep(.errorItem) {
    right: 5%;
    font-size: calc(var(--font-size) - 4px);
    left: unset;
    position: absolute;
    color: var(--error-font-color);
    cursor: default;
    pointer-events: none;
}

:deep(.el-drawer__header) {
    margin: 0 !important;
    padding: 0;
}

:deep(.el-scrollbar__bar.is-vertical) {
    width: 0;
}

:deep(.el-drawer__body) {
    overflow: hidden;
}

:deep(.el-collapse-item.is-disabled .el-collapse-item__header) {
    cursor: default;
    color: #303133;
}

:deep(.is-disabled .el-collapse-item__arrow) {
    display: none;
}

:deep(.empty-tag) {
    display: block;
    margin: 5px auto 0 auto;
    text-align: center;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    width: 99%;
}

:deep(.comment) {
    position: absolute;
    left: 200px;
    top: 12px;
    cursor: default;
    z-index: 999;
    border-radius: 15px;
}

:deep(.title-header .el-collapse-item__header) {
    font-size: calc(var(--font-size) + 3px);
    font-weight: var(--font-weight);
}

:deep(.title-h2 .el-collapse-item__header) {
    font-size: var(--font-size);
    font-weight: var(--font-weight);
}

:deep(.el-textarea__inner),
:deep(.el-textarea) {
    height: calc(100vh - 250px) !important;
}

:deep(.hljs) {
    padding: 5px 10px;
}

:deep(pre),
:deep(code) {
    font-family: inherit;
    font-size: var(--font-size);
    height: fit-content;
    margin: 0;
    overflow: auto;
    background: transparent
}

:deep(.el-button + .el-button) {
    margin-left: 10px !important;
    ;
}

.api {
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    z-index: 998;
    background: rgba(0, 0, 0, .3);
}

.return-data :last-child {
    border: 0 !important;
}

:deep(.el-collapse-item__content .el-row) {
    margin-top: 0 !important;
}

:deep(.el-table .cell) {
    height: fit-content;
    line-height: inherit;
    font-size: var(--font-size);
    padding: 5px !important;
}

:deep(.params .params-value .cell) {
    display: flex;
    justify-content: center;
    align-items: center;
}

:deep(.cost) {
    position: absolute;
    top: 10px;
    right: 30px;
    font-size: calc(var(--font-size) - 3px);
}

:deep(.el-input__inner) {
    height: fit-content;
    font-family: var(--font-family);
    font-weight: var(--font-weight);
    padding: 5px;
}

:deep(.el-input--small) {
    font-size: var(--font-size);
}

:deep(.api-header) {
    display: flex;
    padding: 5px;
    flex-wrap: wrap;
    gap: 50px;
}

.mobile .api-header {
    gap: 5px
}
</style>

<style>
.mobile .params-value .cell:has(.el-input) {
    padding: 5px;
}

.mobile .params-value .cell .errorItem {
    right: unset
}

.mobile .params-value .cell:has(.is-focus) .errorItem {
    display: none;
}

.mobile .params .el-collapse-item__content {
    display: flex;
    justify-content: center;
}

.use-el-message-box .wxmp {
    width: 120px;
    height: 120px;
    border-radius: 50%;
}

.interface-help {
    top: calc((100% - 580px)/2);
}

.mobile .interface-help {
    left: 10px;
    right: 10px;
    max-width: 350px;
}

.dark .request-table .el-input__wrapper {
    background: transparent;
}
</style>